package com.jwsoft.manager.core.dao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.base.common.util.CommonSecureUtil;
import com.jwsoft.manager.common.enums.EduStatusTypeEnum;
import com.jwsoft.manager.common.vo.eduDataTaskDetail.DataTaskDetailOptionVO;
import com.jwsoft.manager.core.dao.mapper.EduhSocialSecurityMapper;
import com.jwsoft.manager.core.dao.mapper.EdutSocialSecurityMapper;
import com.jwsoft.manager.core.dao.model.*;
import com.jwsoft.manager.core.dao.mapper.EduSocialSecurityMapper;
import com.jwsoft.manager.core.dao.service.EduDataTaskDetailService;
import com.jwsoft.manager.core.dao.service.EduSocialSecurityService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwsoft.manager.core.dao.service.TableService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 参保记录表服务实现类
 *
 * @author wangtao
 * @since 2022-12-28
 */
@Service
@Slf4j
public class EduSocialSecurityServiceImpl extends ServiceImpl<EduSocialSecurityMapper, EduSocialSecurity> implements EduSocialSecurityService, TableService {

    @Autowired
    private EduDataTaskDetailService detailService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private EduhSocialSecurityMapper hSocialSecurityMapper;

    @Autowired
    private EdutSocialSecurityMapper tSocialSecurityMapper;

    private static final String SOCIAL_SECURITY = "edu_social_security";

    //每次处理的数量为1w条数据
    private static final Integer PAGE_SIZE = 10000;

    @Override
    public Integer dataMigration(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduSocialSecurityServiceImpl服务的dataMigration()来进行处理迁移数据");
        Integer count = this.baseMapper.selectCountByYear(optionVO.getYear());
        log.info("edu_social_security迁移" + count + "条数据");
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduSocialSecurity> eduSocialSecurityList =
                    this.baseMapper.selectByYear(optionVO.getYear(),PAGE_SIZE);
            if (eduSocialSecurityList.size() > 0) {
                List<EduhSocialSecurity> hSocialSecurities = eduSocialSecurityList.stream().map(item -> {
                    EduhSocialSecurity eduhSocialSecurity = new EduhSocialSecurity();
                    BeanUtils.copyProperties(item, eduhSocialSecurity);
                    eduhSocialSecurity.setTaskDetailId(taskDetail.getTaskDetailId());
                    //数据是否已加密，初始状态未加密
                    eduhSocialSecurity.setEncryptFlag(BoolEnum.FALSE.getType());
                    eduhSocialSecurity.setEncryptStatus(EduStatusTypeEnum.dcl.getType());
                    eduhSocialSecurity.setCleanFlag(BoolEnum.FALSE.getType());
                    return eduhSocialSecurity;
                }).collect(Collectors.toList());
                try {
                    this.performDataMigration(hSocialSecurities, eduSocialSecurityList.size() , optionVO);
                } catch (Exception e) {
                    log.error("edu_social_security迁移数据发生异常");
                    throw new RuntimeException("EduSocialSecurityServiceImpl:" + e);
                }
            }
        }
        return count;
    }

    private void performDataMigration(List<EduhSocialSecurity> hSocialSecurities, Integer count, DataTaskDetailOptionVO optionVO) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    //1.数据迁移到历史表
                    int saveHCount = hSocialSecurityMapper.saveBatch(hSocialSecurities);
                    if (saveHCount != count) {
                        throw new RuntimeException("数据迁移到历史表失败");
                    }
                    //2.数据销毁
                    EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
                    if (ObjectUtils.isEmpty(taskDetail)) {
                        throw new AppException("任务数据不存在，请检查数据是否有误");
                    }
                    Integer deleteCount = baseMapper.deleteByTaskHistory(taskDetail.getTaskDetailId());
                    if (!count.equals(deleteCount)) {
                        throw new RuntimeException("数据删除失败");
                    }
                    log.info("eduh_social_security数据销毁成功！销毁数量：" + count);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

    @Override
    public void dataEncryption(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduSocialSecurityServiceImpl服务的dataEncryption()来进行处理数据加密");
        Integer count = 0;
        if (taskDetail.getEncryptCount() == 0) {
            count = this.baseMapper.selectEncryptionCountByYear(optionVO.getYear(), optionVO.getTaskDetailId());
            taskDetail.setEncryptCount(count);
        }
        Boolean errorFlag = false;
        Integer errorCount = 0;
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhSocialSecurity> eduhSocialSecurities =
                    this.baseMapper.selectEncryptionByYear(optionVO.getYear(), optionVO.getTaskDetailId(),PAGE_SIZE);
            for (EduhSocialSecurity hSocialSecurity : eduhSocialSecurities) {
                //加密
                try {
                    this.encrypt(hSocialSecurity);
                    hSocialSecurity.setEncryptTime(new Date());
                    hSocialSecurity.setEncryptStatus(EduStatusTypeEnum.success.getType());
                    hSocialSecurity.setEncryptRemarks("加密成功");
                    hSocialSecurity.setEncryptFlag(BoolEnum.TRUE.getType());
                    hSocialSecurityMapper.updateById(hSocialSecurity);
                } catch (Exception e) {
                    //解密
                    this.decrypt(hSocialSecurity);
                    hSocialSecurity.setEncryptTime(new Date());
                    hSocialSecurity.setEncryptStatus(EduStatusTypeEnum.error.getType());
                    hSocialSecurity.setEncryptFlag(BoolEnum.FALSE.getType());
                    hSocialSecurity.setEncryptRemarks("加密失败" + e.getMessage());
                    hSocialSecurityMapper.updateById(hSocialSecurity);
                    errorFlag = true;
                    errorCount++;
                    throw new AppException(e);
                }
            }
        }

        if (!errorFlag) {
            //无异常，返回任务状态
            taskDetail.setEncryptStatus(EduStatusTypeEnum.success.getType());
            taskDetail.setEncryptRemarks("加密成功");
            taskDetail.setEncryptTime(new Date());
        } else {
            taskDetail.setEncryptStatus(EduStatusTypeEnum.error.getType());
            taskDetail.setEncryptTime(new Date());
            taskDetail.setEncryptRemarks(taskDetail.getHandleTable()
                    + "加密失败,加密出错的数据：" + errorCount);
        }
        detailService.updateById(taskDetail);
    }

    private void decrypt(EduhSocialSecurity hSocialSecurity) {
        if (StringUtils.isNotBlank(hSocialSecurity.getAac003())) {
            hSocialSecurity.setAac003(CommonSecureUtil.sm4Decrypt(hSocialSecurity.getAac003()));
        }
        if (StringUtils.isNotBlank(hSocialSecurity.getAac147())) {
            hSocialSecurity.setAac147(CommonSecureUtil.sm4Decrypt(hSocialSecurity.getAac147()));
        }
    }

    private void encrypt(EduhSocialSecurity hSocialSecurity) {
        if (StringUtils.isNotBlank(hSocialSecurity.getAac003())) {
            hSocialSecurity.setAac003(CommonSecureUtil.sm4Encrypt(hSocialSecurity.getAac003()));
        }
        if (StringUtils.isNotBlank(hSocialSecurity.getAac147())) {
            hSocialSecurity.setAac147(CommonSecureUtil.sm4Encrypt(hSocialSecurity.getAac147()));
        }
    }

    /**
     * 参保清洗规则
     * 2022年的数据 ：保留
     * 2023年的数据：根据报名表中的社保id进行报错
     * @param optionVO
     * @return
     */
    @Override
    public Integer dataDestruction(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduSocialSecurityServiceImpl服务的dataDestruction来进行处理数据清洗");

        Boolean queryHistory =
                detailService.verifyQueryHistory(optionVO.getYear(), SOCIAL_SECURITY);
        List<EduhSocialSecurity> hSocialSecurities = new ArrayList<>();
        if (queryHistory){
            //查询历史表报名数据
            hSocialSecurities = this.baseMapper.queryHistoryEnrollCleanSocial
                    (taskDetail.getYear(),taskDetail.getTaskDetailId());
        }else{
            //查询在线表报名数据
            hSocialSecurities = this.baseMapper.queryEnrollCleanSocial
                    (taskDetail.getYear(),taskDetail.getTaskDetailId());
        }
        Integer cleanCount = hSocialSecurities.size();
        if (cleanCount != 0){
            try {
                int batchSize = 1000;
                for (int i = 0; i<hSocialSecurities.size(); i+= batchSize){
                    int endIndex = Math.min(i + batchSize, hSocialSecurities.size());
                    List<EduhSocialSecurity> eduhSocialSecurities = hSocialSecurities.subList(i, endIndex);
                    this.preformDataClean(eduhSocialSecurities);
                 }
            } catch (Exception e) {
                log.error("eduh_social_security数据清洗发生异常");
                throw new RuntimeException("EduSocialSecurityServiceImpl:" + e);
            }
        }
        return cleanCount;
    }

    private void preformDataClean(List<EduhSocialSecurity> hSocialSecurities) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    List<EdutSocialSecurity> tSocialSecurityList = hSocialSecurities.stream().map(item -> {
                        EdutSocialSecurity tSocialSecurity = new EdutSocialSecurity();
                        BeanUtils.copyProperties(item, tSocialSecurity);
                        tSocialSecurity.setCleanFlag(BoolEnum.TRUE.getType());
                        return tSocialSecurity;
                    }).collect(Collectors.toList());
                    tSocialSecurityMapper.saveBatch(tSocialSecurityList);
                    for (EduhSocialSecurity hSocialSecurity : hSocialSecurities) {
                        hSocialSecurityMapper.deleteHistoryById(hSocialSecurity.getSocialSecurityId());
                    }
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

    @Override
    public void tempDataDestruction() {
        System.out.println("空闲数据销毁");
    }

    @Override
    public void dataDecrypt(DataTaskDetailOptionVO optionVO) {
        Integer count = Math.toIntExact(hSocialSecurityMapper.selectCount(new QueryWrapper<EduhSocialSecurity>().lambda().eq(EduhSocialSecurity::getTaskDetailId, optionVO.getTaskDetailId())));
        // 计算总页数
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        int currentPage = 0;
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhSocialSecurity> eduhSocialSecurities =
                    hSocialSecurityMapper.selectByTaskDetailId(optionVO.getTaskDetailId(),currentPage,PAGE_SIZE);
            List<EdutSocialSecurity> edutSocialSecurityList = eduhSocialSecurities.stream().map(eduhSocialSecurity -> {
                if (BoolEnum.TRUE.getType().equalsIgnoreCase(eduhSocialSecurity.getEncryptFlag())) {
                    //需要进行解密
                    this.decrypt(eduhSocialSecurity);
                }
                EdutSocialSecurity edutSocialSecurity = new EdutSocialSecurity();
                BeanUtils.copyProperties(eduhSocialSecurity, edutSocialSecurity);
                return edutSocialSecurity;
            }).collect(Collectors.toList());
            tSocialSecurityMapper.saveBatch(edutSocialSecurityList);
            currentPage ++;
        }

    }
}
